const User = require('./User')

class Users {
    constructor(dao) {
        this.dao = dao
        this._fp = new Map()
        this._name = new Map()
        this._sid = new Map()
    }
    find({ sid, fp, name }) {
        return this._fp.get(fp)
            || this._sid.get(sid)
            || this._name.get(name)
    }
    inspector() {
        let res = []
        for (let i of this._name.keys()) {
            res.push(i)
        }
        return res
    }
    remove(user) {
        let { fp, name, socket } = user
        this._fp.delete(fp)
        this._sid.delete(socket.id)
        this._name.delete(name)
        return this
    }
    add(user) {
        let { fp, name, socket } = user
        this._fp.set(fp, user)
        this._sid.set(socket.id, user)
        this._name.set(name, user)
        return this
    }
    async conn(fp, socket) {
        let user = this.find({ fp })
        if (user) {
            // 如果存在，更新
            this.remove(user)
            user.socket = socket
        } else {
            // 否则从数据库中加载信息
            let { type, name, alias } = await this.dao.userInfo({ fp })
            if (!type) {
                // 如果数据库中没有
                name = Math.random().toString(36).substring(5)
                type = '临时用户'
                // 存入数据库和缓存
                await this.dao.newGuest(name, fp)
            }
            user = new User({ fp, socket, alias, type, name })
        }
        this.add(user)
        return user
    }

    async newUser({ name, alias }, newName, password, socket) {
        this.dao.newUser(name, newName, password, alias)
        let user = this.find({ name })
        return user.setInfo({ name: newName, alias, socket })
    }

    async login(name, user) {
        // 根据流程，login 必然在 conn 之后
        let { alias, type, fingerprint } = await this.dao.userInfo({ name })
        user.setInfo({ name, type, alias, fp: fingerprint })
        user.setPermission(await this.dao.permissions(name))
        return this
    }
    async signup(name, password) {
        this.dao.newUser(name, password)
    }
}

module.exports = Users